package com.expense.services;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;

import com.expense.annotation.Column;
import com.expense.annotation.InvokClass;
import com.expense.annotation.Table;
import com.expense.dao.Dao;
import com.expense.entity.UserInfo;
import com.expense.util.PaginatedList;

/**
 * Services基类
 * @author xj
 * */
public class BasicServices {
	public Logger logger = Logger.getLogger(this.getClass());
	public InvokClass invokClass=new InvokClass();
	
	/**
	 * 得到会话用户对象
	 * **/
	public UserInfo getLoginAdmin(HttpServletRequest request){
			HttpSession session=request.getSession();
			UserInfo  loginAdmin=(UserInfo) session.getAttribute("loginAdmin");
			return loginAdmin;
	}
	
	/**
	 * 获取对象表名
	 * **/
	public String getTableName(Class objClass){
		String tableName=null;
		//判断该类上是不是存在Table类型的注解   
        if(objClass.isAnnotationPresent(Table.class)){   
           //存在   
        	Table table = (Table) objClass.getAnnotation(Table.class);//获取实例   
            //获取元素值   
        	tableName = table.tableName(); 
        }
        return tableName;
	}
	
	/**
	 * 对象字段和列信息的键值
	 * @return
	 *  key String  属性名称
	 *  value Object[]  列名-String,是否为主键-boolean,日期格式-int,属性简短类型-String
	 * */
	public Map<String, Object[]> getFieldColumnInfoOrm(Class objClass) {
		 Map<String, Object[]> fieldColumnMap=new HashMap<String, Object[]>();
		Field[] fields=objClass.getDeclaredFields();
	    for(int i =0;i<fields.length;i++){
    	       Field field = fields[i];
    	       String fieldName= field.getName(); //属性名称
    	       Class fieldClass = field.getType(); //获取属性字段类型
    	       //String fieldTypeName=fieldClass.getName();//类型名称
    	       String fieldSimpleTypeName=fieldClass.getSimpleName();//简短类型名称
    	       
    	       String columnName="";
    	       boolean isPrimaryKey=false;
    	       int dateTimeType=0;
    	       //判断该成员变量上是不是存在Column类型的注解   
               if(field.isAnnotationPresent(Column.class)){   
                  //存在   
                  Column column = field.getAnnotation(Column.class);//获取实例   
                   //获取元素值   
                  columnName = column.columnName();
                  isPrimaryKey=column.isPrimaryKey();
                  dateTimeType=column.dateTimeType();
                  fieldColumnMap.put(fieldName, new Object [] {columnName,isPrimaryKey,dateTimeType,fieldSimpleTypeName});
               }
		
	    }
		return fieldColumnMap;
	}
	
	
	
	/**
	 * 根据ResultSet得到单个对象
	 * **/
	public Object getSingleObject(ResultSet rs,Class objClass){
		Object object=null;
		try {
			if(rs!=null) {
				ResultSetMetaData   rsmd=rs.getMetaData();     
				int columnCount=rsmd.getColumnCount();  //总列数
				String [] columnNames=new String [columnCount];//列名数组
				int [] columnTypes=new int [columnCount];//列类型数组
				for (int i = 1; i <= columnCount; i++) {
					columnNames[i-1]=rsmd.getColumnName(i);
					columnTypes[i-1]=rsmd.getColumnType(i);
				}
				if(rs.next()){
					Map<String, Object> valueMap=new HashMap<String, Object>();
					 for (int i = 0; i < columnNames.length; i++) {
						 String columnName=columnNames[i];
						 
						 
						 /*int columnType=columnTypes[i];
						 
						 if(Types.VARCHAR==columnType
								 ||Types.NVARCHAR==columnType){
							 valueMap.put(columnName,rs.getString(columnName));
						 }else if(Types.INTEGER==columnType
								 ||Types.BIT==columnType){
							 valueMap.put(columnName, rs.getInt(columnName));
						 }else if (Types.SMALLINT == columnType) { 
							 valueMap.put(columnName, rs.getShort(columnName));// 此处如果调用rs.getObject方法会返回一个Integer型[DB2] 
						  } else if(Types.DATE == columnType) { 
							  valueMap.put(columnName, rs.getDate(columnName));
						  } else if(Types.DECIMAL==columnType
								  ||Types.FLOAT==columnType
								  ){
							  valueMap.put(columnName,rs.getFloat(columnName));
						  }else if(Types.DOUBLE == columnType) { 
							  valueMap.put(columnName,rs.getDouble(columnName));
						  }*/
						 valueMap.put(columnName,rs.getObject(i+1));
					 }
					 object=objClass.newInstance();
					 object=invokClass.setClassObjInfo(object, valueMap);
				}
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
		return object;
	}
	

	/**
	 * 根据ResultSet得到对象集合
	 * **/
	public List getListObjects(ResultSet rs,Class objClass){
		List<Object> list=new ArrayList<Object>();
		try {
			if(rs!=null) {
				ResultSetMetaData   rsmd=rs.getMetaData();     
				int columnCount=rsmd.getColumnCount(); //总列数
				String [] columnNames=new String [columnCount];//列名数组
				int [] columnTypes=new int [columnCount];//列类型数组
				for (int i = 1; i <= columnCount; i++) {
					columnNames[i-1]=rsmd.getColumnName(i);
					columnTypes[i-1]=rsmd.getColumnType(i);
				}
				while(rs.next()){
					
					Map<String, Object> valueMap=new HashMap<String, Object>();
					 for (int i = 0; i < columnNames.length; i++) {
						 String columnName=columnNames[i];
						 
						 
						 /*int columnType=columnTypes[i];
						 
						 if(Types.VARCHAR==columnType
								 ||Types.NVARCHAR==columnType){
							 valueMap.put(columnName,rs.getString(columnName));
						 }else if(Types.INTEGER==columnType
								 ||Types.BIT==columnType){
							 valueMap.put(columnName, rs.getInt(columnName));
						 }else if (Types.SMALLINT == columnType) { 
							 valueMap.put(columnName, rs.getShort(columnName));// 此处如果调用rs.getObject方法会返回一个Integer型[DB2] 
						  } else if(Types.DATE == columnType) { 
							  valueMap.put(columnName, rs.getDate(columnName));
						  } else if(Types.DECIMAL==columnType
								  ||Types.FLOAT==columnType
								  ){
							  valueMap.put(columnName,rs.getFloat(columnName));
						  }else if(Types.DOUBLE == columnType) { 
							  valueMap.put(columnName,rs.getDouble(columnName));
						  }*/
						 
						 valueMap.put(columnName,rs.getObject(i+1));
						 
						 
						  
						 
						 
					 }
					 //Object object=new  Object();
					 Object object=objClass.newInstance();
					 object=invokClass.setClassObjInfo(object, valueMap);
					 
					 list.add(object);
				}
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return list;		
	}
	
	
	/**
	 * 执行sql语句
	 * */
	public  boolean executeSql(String sql) {
		Dao dao=new Dao();
		logger.info("sql:"+sql);
		boolean iflag=dao.executeSql(sql);
		dao.CloseCon();//关闭此次连接
		return iflag;
	}
	
	
	/**
	 * 查询信息集合
	 * @param sql sql语句
	 * */
	public List selectList(String sql,Class objClass){
		Dao dao=new Dao();
		logger.info("sql:"+sql);
		ResultSet rs=dao.selectData(sql);
		List list=this.getListObjects(rs,objClass);
		dao.CloseCon();//关闭此次连接
		return list;
	}
	 
	
	/**
	 * 查询信息集合
	 * @param whereSql 查询的条件语句 语句中应该带上'where' 关键字
	 * @param orderSql 查询的排序语句 语句中应该带上'order by' 关键字
	 * */
	public List selectList(String whereSql,String orderSql,Class objClass){
		List list=new ArrayList();
		
		String tableName="";
		//判断该类上是不是存在Table类型的注解   
        if(objClass.isAnnotationPresent(Table.class)){   
           //存在   
        	Table table = (Table) objClass.getAnnotation(Table.class);//获取实例   
            //获取元素值   
        	tableName = table.tableName(); 
        }  
		if(!tableName.equals("")){
			String sql=" select * from  "+tableName+" ";
			if(whereSql!=null&&!whereSql.equals("")){
				sql+=" "+whereSql;
			}
			if(orderSql!=null&&!orderSql.equals("")){
				sql+=" "+orderSql;
			}
			
			Dao dao=new Dao();
			ResultSet rs=dao.selectData(sql);
			list=this.getListObjects(rs,objClass);
			dao.CloseCon();//关闭此次连接
		}else{
        	logger.error(objClass.getName()+"对象没有设置表名注解,不能进行此对象的查询信息集合操作!"); 	
        }
		return list;
	}


	
	/**
	 * 查询单个信息
	 * @param id 信息ID
	 * */
	public Object getObjectById(int id,Class objClass){
		Object object=null;
		
		String tableName="";
		//判断该类上是不是存在Table类型的注解   
        if(objClass.isAnnotationPresent(Table.class)){   
           //存在   
        	Table table = (Table) objClass.getAnnotation(Table.class);//获取实例   
            //获取元素值   
        	tableName = table.tableName(); 
        }  	
        if(!tableName.equals("")){
        	
        }
        	if(!tableName.equals("")){
    			String primaryColumnName="";
    			Field[] fields=objClass.getDeclaredFields();
    			 for(int i =0;i<fields.length;i++){
    	    	       Field field = fields[i];
    	    	       
    	    	       String columnName="";
    	    	       boolean isPrimaryKey=false;
    	    	       //判断该成员变量上是不是存在Column类型的注解   
    	               if(field.isAnnotationPresent(Column.class)){   
    	                  //存在   
    	                  Column column = field.getAnnotation(Column.class);//获取实例   
    	                   //获取元素值   
    	                  columnName = column.columnName(); 
    	                  isPrimaryKey=column.isPrimaryKey();
    	               }
    	               
    	               if(isPrimaryKey){
    	            	   primaryColumnName=columnName;
    	               }
    			 }
        	
    			 if(!primaryColumnName.equals("")) {
					String sql=" select * from "+tableName+" where "+primaryColumnName+"="+id;
					Dao dao=new Dao();
					ResultSet rs=dao.selectData(sql);
					object= this.getSingleObject(rs,objClass);
					dao.CloseCon();//关闭此次连接
    			 }else{
    		        	logger.error(objClass.getName()+"对象没有设置主键字段,不能查询单条对象!"); 	
    		      }
        }else{
        	logger.error(objClass.getName()+"对象没有设置表名注解,不能进行此对象的单个信息查询操作!"); 	
        }
		return object;
	}
	
	/**
	 * 删除单个信息
	 * @param id 信息ID
	 * */
	public boolean deleteObjectById(int id,Class objClass){
		boolean iflag=true;
		String tableName="";
		//判断该类上是不是存在Table类型的注解   
        if(objClass.isAnnotationPresent(Table.class)){
           //存在   
        	Table table = (Table) objClass.getAnnotation(Table.class);//获取实例   
            //获取元素值   
        	tableName = table.tableName(); 
        }  	
		
		if(!tableName.equals("")){
			String primaryColumnName="";
			Field[] fields=objClass.getDeclaredFields();
			 for(int i =0;i<fields.length;i++){
	    	       Field field = fields[i];
	    	       
	    	       String columnName="";
	    	       boolean isPrimaryKey=false;
	    	       //判断该成员变量上是不是存在Column类型的注解   
	               if(field.isAnnotationPresent(Column.class)){   
	                  //存在   
	                  Column column = field.getAnnotation(Column.class);//获取实例   
	                   //获取元素值   
	                  columnName = column.columnName(); 
	                  isPrimaryKey=column.isPrimaryKey();
	               }
	               
	               if(isPrimaryKey){
	            	   primaryColumnName=columnName;
	               }
			 }
			
			
			if(!primaryColumnName.equals("")) {
				String sql=" delete from "+tableName+" where "+primaryColumnName+"="+id;
				Dao dao=new Dao();
				iflag=dao.executeSql(sql);
				dao.CloseCon();//关闭此次连接
			}else{
	        	logger.error(objClass.getName()+"对象没有设置主键字段,不能进行此对象的删除操作!"); 	
	        }
		}else{
        	logger.error(objClass.getName()+"对象没有设置表名注解,不能进行此对象的删除操作!"); 	
        }
		return iflag;
	}
	
	
	/**
	 * 分页查询
	 * @param pageSize 每页大小
	 * @param currentPage 当前页数
	 * @param whereSql 查询的条件语句 语句中应该带上'where' 关键字
	 * @param orderSql 查询的排序语句 语句中应该带上'order by' 关键字
	 * */
	public PaginatedList selectPageData(int pageSize ,int currentPage,String whereSql,String orderSql,Class objClass){
		PaginatedList paginatedList=new PaginatedList();
		
		String tableName="";
		//判断该类上是不是存在Table类型的注解   
        if(objClass.isAnnotationPresent(Table.class)){   
           //存在   
        	Table table = (Table) objClass.getAnnotation(Table.class);//获取实例   
            //获取元素值   
        	tableName = table.tableName(); 
        }  	
		
		if(!tableName.equals("")){
			String primaryColumnName="";
			Field[] fields=objClass.getDeclaredFields();
			 for(int i =0;i<fields.length;i++){
	    	       Field field = fields[i];
	    	       
	    	       String columnName="";
	    	       boolean isPrimaryKey=false;
	    	       //判断该成员变量上是不是存在Column类型的注解   
	               if(field.isAnnotationPresent(Column.class)){   
	                  //存在   
	                  Column column = field.getAnnotation(Column.class);//获取实例   
	                   //获取元素值   
	                  columnName = column.columnName(); 
	                  isPrimaryKey=column.isPrimaryKey();
	               }
	               
	               if(isPrimaryKey){
	            	   primaryColumnName=columnName;
	               }
			 }
			
			
			Dao dao=new Dao();
			ResultSet rs=dao.pageResultSetData(pageSize, currentPage, tableName,primaryColumnName,whereSql, orderSql);
			List list=this.getListObjects(rs,objClass);
			 
			paginatedList=dao.paginatedListData(pageSize, currentPage, tableName, whereSql, orderSql);
			paginatedList.setDataList(list);
			
			dao.CloseCon();//关闭此次连接
		}else{
        	logger.error(objClass.getName()+"对象没有设置表名注解,不能进行此对象的分页查询操作!"); 	
        }
		return paginatedList;
		
	}
	
	
	
	/**
	 * 新增单个对象信息
	 * @param object 单个对象
	 * */
	public int addObjectInfo(Object object){
		int id=0;
		String tableName="";
		//判断该类上是不是存在Table类型的注解   
        if(object.getClass().isAnnotationPresent(Table.class)){   
           //存在   
        	Table table = (Table) object.getClass().getAnnotation(Table.class);//获取实例   
            //获取元素值   
        	tableName = table.tableName(); 
        }
        String addSql="";
        if(!tableName.equals("")){
        	addSql="insert into "+tableName+" ";
        	
        	Field[] fields=object.getClass().getDeclaredFields();
        	
        	
        	String elementSql="(";
        	String valueSql="(";
        	
    	    for(int i =0;i<fields.length;i++){
	    	       Field field = fields[i];
	    	       String fieldName= field.getName(); //属性名称
	    	       Class fieldClass = field.getType(); //获取属性字段类型
	    	       String fieldTypeName=fieldClass.getName();//类型名称
	    	       String fieldSimpleTypeName=fieldClass.getSimpleName();//简短类型名称
	    	       
	    	       String columnName="";
	    	       boolean isPrimaryKey=false;
	    	       int dateTimeType=0;
	    	       //判断该成员变量上是不是存在Column类型的注解   
	               if(field.isAnnotationPresent(Column.class)){   
	                  //存在   
	                  Column column = field.getAnnotation(Column.class);//获取实例   
	                   //获取元素值   
	                  columnName = column.columnName();
	                  isPrimaryKey=column.isPrimaryKey();
	                  dateTimeType=column.dateTimeType();
	               }
	        	   
	               if(!columnName.equals("")&&!isPrimaryKey){//有列名的
	            	   if(!elementSql.equals("(")){
	            		   elementSql+=",";
	            	   }
	            	   elementSql+=""+columnName+"";
	            	   
	            	   Object value=invokClass.getValueinvokMethod(fieldName, object);
	            	   
	            	   if(!valueSql.equals("(")){
	            		   valueSql+=",";
	            	   }
	            	   
	            	   if(value==null){
	            		   valueSql+="null";
	            	   }else{    	  
	            		   System.out.println(fieldName+":"+fieldSimpleTypeName);
		            	   if(fieldSimpleTypeName.equals("Date")){
		            		   SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		            		   SimpleDateFormat sdfLong=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		            		   Date thedate=(Date) value; 
		            		   String dateValue="";
		            		   if(dateTimeType==1)   
		            				dateValue=sdfLong.format(thedate);
		            		   else 
		            			   dateValue=sdf.format(thedate);
		            		   
		            		   valueSql+="'"+dateValue+"'";
		            	   }else if(fieldSimpleTypeName.equals("Boolean")||fieldSimpleTypeName.equals("boolean")){
		            			Boolean valueIflag=(Boolean) value;  
		            		    if(valueIflag){
		            		    	valueSql+=1;
		            		    }else{
		            		    	valueSql+=0;
		            		    }
		            		   
		            	   }else if(fieldSimpleTypeName.equals("Integer")
		            			   ||fieldSimpleTypeName.equals("Float")
		            			   ||fieldSimpleTypeName.equals("Double")
		            			    ||fieldSimpleTypeName.equals("Long")
		            			    ||fieldSimpleTypeName.equals("BigDecimal")
		            			    
		            			   ){
		            		   
		            		   
		            		   
		            		   valueSql+=value;
		            	   }else{
		            		   
		            			   valueSql+="N'"+value+"'";
		            		  
		            	   }
	            	   }
	            	   
	               }
              }
    	    
    	    elementSql+=")";
        	valueSql+=")";
        	
        	addSql+=" "+elementSql+" values "+valueSql;     
        	
        	logger.info("addSql:"+addSql);
        	Dao dao=new Dao();
    		id=dao.executeInsertSql(addSql);
    		dao.CloseCon();//关闭此次连接
        }else{
        	logger.error(object.getClass().getName()+"对象没有设置表名注解,不能进行此对象的新增操作!"); 	
        }
       return id; 
	}
	
	
	/**
	 * 修改单个对象信息
	 * @param object 单个对象
	 * */
	public boolean updateObjectInfo(Object object){
		boolean iflag=false;
		String tableName="";
		//判断该类上是不是存在Table类型的注解   
        if(object.getClass().isAnnotationPresent(Table.class)){   
           //存在   
        	Table table = (Table) object.getClass().getAnnotation(Table.class);//获取实例   
            //获取元素值   
        	tableName = table.tableName(); 
        }
        String updateSql="";
        if(!tableName.equals("")){
        	updateSql="update "+tableName+" set ";
        	
        	Field[] fields=object.getClass().getDeclaredFields();
        	
        	String elementSql="";
        	
        	String primaryFieldName="";//主键字段属性
        	Object primaryValue=null;//主键属性字段值
        	String primaryColumnName="";
    	    for(int i =0;i<fields.length;i++){
	    	       Field field = fields[i];
	    	       String fieldName= field.getName(); //属性名称
	    	       Class fieldClass = field.getType(); //获取属性字段类型
	    	       String fieldTypeName=fieldClass.getName();//类型名称
	    	       String fieldSimpleTypeName=fieldClass.getSimpleName();//简短类型名称
	    	       
	    	       String columnName="";
	    	       boolean isPrimaryKey=false;
	    	       int dateTimeType=0;
	    	       //判断该成员变量上是不是存在Column类型的注解   
	               if(field.isAnnotationPresent(Column.class)){   
	                  //存在   
	                  Column column = field.getAnnotation(Column.class);//获取实例   
	                   //获取元素值   
	                  columnName = column.columnName(); 
	                  isPrimaryKey=column.isPrimaryKey();
	                  dateTimeType=column.dateTimeType();
	               }
	               
	               if(isPrimaryKey){
	            	   primaryFieldName=fieldName;
	            	   Object idValue=invokClass.getValueinvokMethod(primaryFieldName, object);
	            	   primaryValue=idValue;
	            	   
	            	   primaryColumnName=columnName;
	               }
	        	   
	               if(!columnName.equals("")&&!isPrimaryKey){//有列名的
	            	   
	            	   Object value=invokClass.getValueinvokMethod(fieldName, object);
	            	   
	            	   if(!elementSql.equals("")){
	            		   elementSql+=",";
	            	   }  	   
	            	   
	            	   
	            	   if(value==null){
	            		   elementSql+=""+columnName+"=null ";
	            	   }else{    	   
		            	   if(fieldSimpleTypeName.equals("Date")){
		            		   SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
		            		   SimpleDateFormat sdfLong=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		            		   Date thedate=(Date) value; 
		            		   String dateValue="";
		            		   if(dateTimeType==1)   
		            				dateValue=sdfLong.format(thedate);
		            		   else 
		            			   dateValue=sdf.format(thedate);
		            		   elementSql+=""+columnName+"='"+dateValue+"' ";
		            	   }else if(fieldSimpleTypeName.equals("Boolean")||fieldSimpleTypeName.equals("boolean")){
		            		   Boolean valueIflag=(Boolean) value;  
		            		    if(valueIflag){
		            		    	 elementSql+=""+columnName+"="+1+" ";
		            		    }else{
		            		    	 elementSql+=""+columnName+"="+0+" ";
		            		    }
		            		   
		            	   }else if(fieldSimpleTypeName.equals("Integer")
		            			   ||fieldSimpleTypeName.equals("Float")
		            			   ||fieldSimpleTypeName.equals("Double")
		            			   ||fieldSimpleTypeName.equals("Long")
		            			   ||fieldSimpleTypeName.equals("BigDecimal")
		            			   ){
		            		   elementSql+=""+columnName+"="+value+" ";
		            	   }else{
		            		   elementSql+=""+columnName+"=N'"+value+"' "; 
		            	   }
	            	   } 
	               }
              }
    	    
    	    
    	    
    	     
        	
    	    updateSql+=" "+elementSql+" where  "+primaryColumnName+"="+primaryValue;     
        	
        	logger.info("updateSql:"+updateSql);
	        	if(primaryValue!=null&&!primaryColumnName.equals("")){
	        	Dao dao=new Dao();
	        	iflag=dao.executeSql(updateSql);
	        	dao.CloseCon();//关闭此次连接
        	}
        }else{
        	logger.error(object.getClass().getName()+"对象没有设置表名注解,不能进行此对象的修改操作!"); 	
        }
       return iflag; 
	}
	
	
	
	 
	
	
	
	
	
	
	
	
	
	
	public static void main(String[] args) {
		BasicServices basicServices=new BasicServices();
		
		/*Dao dao=new Dao();
		String sql="select * from user_info";
		ResultSet resultSet=dao.selectData(sql);
		basicServices.getListObjects(resultSet,UserInfo.class);
		dao.CloseCon();*/
		
		 
	}
}
